import {
  Action,
  getModule,
  Module,
  Mutation,
  VuexModule
} from 'vuex-module-decorators'

import type { AliOssUploadToken, ApiType } from '@/api/sys/model/ossModel'
import { getAliOssUploadTokenApi } from '@/api/sys/oss'
import { hasCacheB } from '@/store/plugins'

import store from '../instance'

interface OssState {
  /* 静态获取token */
  readonly ossToken: MaybeNull<AliOssUploadToken>

  /* 自动获取token */
  getOssToken(apiType: ApiType): Promise<AliOssUploadToken>
}

@Module({
  namespaced: true,
  name: 'oss',
  dynamic: true,
  store,
  preserveState: hasCacheB('oss')
})
export class Oss extends VuexModule implements OssState {
  private _ossToken: MaybeNull<AliOssUploadToken> = null

  get ossToken() {
    return this._ossToken as AliOssUploadToken
  }

  @Mutation
  setOssToken(val: AliOssUploadToken) {
    this._ossToken = val
  }

  @Mutation
  $resetState() {
    this._ossToken = null
  }

  @Action
  async _getOssUploadTokenAction() {
    const result = await getAliOssUploadTokenApi()
    this.setOssToken(result)
    return result
  }

  @Action
  async getOssToken() {
    const checkToken = () => {
      const { expire = 0 } = this.ossToken || {}
      return Number(expire) - ~~(Date.now() / 1000) > 300
    }

    if (!checkToken()) {
      const result = await this._getOssUploadTokenAction()
      return result
    } else {
      return this.ossToken as AliOssUploadToken
    }
  }
}

export const ossStore = getModule<Oss>(Oss)
